declare module "cat" {
  namespace Types {
    namespace Xhr {
      interface Progress extends CM_Types.Xhr.Progress {
        readonly done?: typeof ProgressEvent.prototype.loaded;
        readonly responseType?: XMLHttpRequestResponseType;
        readonly totalSize?: typeof ProgressEvent.prototype.total;
      }
      interface Response extends CM_Types.Xhr.Response {
        readonly responseType?: XMLHttpRequestResponseType;
      }
      interface Details extends CM_Types.Xhr.Details {
        anonymous?: boolean;
        cookie?: string;
        data?:
          | string
          | Blob
          | File
          | Record<string | number, unknown>
          | Array<unknown>
          | FormData;
        fetch?: boolean;
        maxRedirects?: number;
        nocache?: boolean;
        responseType?: XMLHttpRequestResponseType | "stream";
        url: string | URL;
        onabort?: () => void;
        onerror?: (this: Details, err: string) => void;
        onload?: (this: Details, e: Response) => void;
        onloadend?: (this: Details, e: Response) => void;
        onloadstart?: (this: Details, e: Response) => void;
        onprogress?: (this: Details, e: Progress) => void;
        onreadystatechange?: (this: Details, e: Response) => void;
        ontimeout?: (this: Details) => void;
      }
    }
    namespace Download {
      interface Error {
        error:
          | "not_enabled"
          | "not_whitelisted"
          | "not_permitted"
          | "not_supported"
          | "not_succeeded"
          | "unknown";
        details?: string;
      }
      interface Config {
        url: Parameters<typeof browser.downloads.download>[0]["url"];
        name?: Parameters<typeof browser.downloads.download>[0]["filename"];
        onload?: (this: Config, e: Xhr.Response) => void;
        onprogress?: (this: Config, e: Xhr.Progress) => void;
        onerror?: (this: Config, e: Error) => void;
        ontimeout?: () => void;
      }
      interface Details extends Config {
        anonymous?: boolean;
        cookie?: string;
        headers?: Parameters<typeof browser.downloads.download>[0]["headers"];
        method?: Parameters<typeof browser.downloads.download>[0]["method"];
        saveAs?: Parameters<typeof browser.downloads.download>[0]["saveAs"];
        timeout?: number;
      }
    }
    namespace Notification {
      interface Button {
        iconUrl?: string;
        title: string;
      }
      interface Option extends Partial<CM_Types.Notification.Option> {
        buttons?: [Button?, Button?];
        highlight?: boolean;
        progress?: number;
        silent?: boolean;
        timeout?: number;
        onclick?: (
          this: Record<"id", string>,
          id: string,
          index?: number,
        ) => void;
        oncreate?: (this: Record<"id", string>, id: string) => void;
        ondone?: (this: Record<"id", string>, clicked: boolean) => void;
      }
    }
    namespace Vcl {
      type cbFunction = (
        this: cbThis,
        name: string,
        oldValue: unknown,
        newValue: unknown,
        remote: boolean,
        tabid?: number,
      ) => void;
      interface cbThis {
        readonly name: string;
        readonly listener: cbFunction;
      }
    }
    namespace OpenTab {
      interface Option {
        active?: boolean;
        insert?: boolean;
        setParent?: boolean;
        useOpen?: boolean;
      }
      interface Result {
        close(): void;
        readonly closed: boolean;
      }
    }
    interface ClipboardDataType {
      type?: string;
      mimetype?: string;
    }
    namespace Cookie {
      type Method = "list" | "delete" | "set" | "store";
      interface SetDetails
        extends Omit<Parameters<typeof browser.cookies.set>[0], "domain"> {
        domain: string;
      }
      type DeleteDetails = Partial<
        Parameters<typeof browser.cookies.remove>[0]
      >;
      type ListDetails = Parameters<typeof browser.cookies.getAll>[0];
      type Callback = (
        cookies?: browser.cookies.Cookie[],
        error?: string,
      ) => void;
    }
    namespace FileStorage {
      interface Error {
        code: -1 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
        error: string;
      }
      interface FileInfo {
        name: string;
        path: string;
        absPath: string;
        size: number;
        digest: string;
        createtime: number;
        updatetime: number;
      }
    }
    namespace UserConfig {
      type ConfigType =
        | "text"
        | "checkbox"
        | "select"
        | "mult-select"
        | "number"
        | "textarea"
        | "time";
      interface Config {
        [key: string]: unknown;
        title: string;
        description: string;
        default?: unknown;
        type?: ConfigType;
        bind?: string;
        values?: unknown[];
        password?: boolean;
        max?: number;
        min?: number;
        rows?: number;
      }
    }
  }
}
